<template>

	<Card mode = "users">
		<div class = "controls">
			<el-button type = "success" :disabled = "!userStore.isAdmin" @click = "openAddDialog">新增用户</el-button>
		</div>
		<el-table height = "80vh" :data = "filterUsers" v-loading = "loading" row-key = "id">
			<el-table-column type = "selection" width = "55" :selectable = "selectable" />
			<el-table-column prop = "username" label = "用户名" />
			<el-table-column prop = "email" label = "邮箱" />
			<el-table-column prop = "role" label = "权限" />
			<el-table-column fixed = "right" label = "操作" min-width = "120">
				<template #header>
					<el-input v-model = "search" size = "small" placeholder = "键入关键字搜索" />
				</template>
				<template #default = "scope">
					<el-button
						link
						type = "primary"
						size = "small"
						:disabled = "!userStore.isAdmin"
						@click.prevent = "EditRow(scope.row)"
					>
						编辑
					</el-button>
					<el-popconfirm title = "是否确认删除?" @confirm = "deleteRow(scope.row)">
						<template #reference>
							<el-button
								link
								type = "danger"
								size = "small"
								:disabled = "!userStore.isAdmin"
							>
								删除
							</el-button>
						</template>
					</el-popconfirm>
				</template>
			</el-table-column>
		</el-table>
	</Card>

	<el-dialog v-model = "dialogFormVisible" title = "编辑用户信息" width = "500">
		<el-form
			ref = "ruleFormRef"
			:model = "ruleForm"
			:rules = "rules"
			status-icon
		>
			<el-form-item label = "用户名" prop = "username">
				<el-input v-model = "ruleForm.username" autocomplete = "off" />
			</el-form-item>
			<!--<el-form-item label = "密码">-->
			<!--  <el-input v-model = "editUser.password" autocomplete = "off" />-->
			<!--</el-form-item>-->
			<el-form-item label = "邮箱" prop = "email">
				<el-input v-model = "ruleForm.email" autocomplete = "off" />
			</el-form-item>
			<el-form-item label = "权限" prop = "role">
				<el-select v-model = "ruleForm.role" placeholder = "请选择权限"
						   :disabled = "!userStore.isAdmin">
					<el-option label = "管理员" value = "ADMIN"></el-option>
					<el-option label = "普通用户" value = "USER"></el-option>
				</el-select>
			</el-form-item>
		</el-form>
		<template #footer>
			<div class = "dialog-footer">
				<el-button @click = "closeEditDialog">取消</el-button>
				<el-button type = "primary" @click = "submitEdit(ruleFormRef)">
					{{ op === 'add' ? '添加' : '更新' }}
				</el-button>
				<el-button :disabled = "!userStore.isAdmin">仅管理员可见</el-button>
			</div>
		</template>
	</el-dialog>

</template>

<script lang = "ts" setup>
import Api from '@/api'
import { computed, onMounted, reactive, ref } from 'vue'
import Card from '@/components/Card.vue'
import simpleRequest from '@/utils/requestUtils'
import useStore from '@/store'
import { FormInstance, FormRules } from 'element-plus'
import { showMessage } from '@/utils/messageUtils'


//* Store
const { userStore } = useStore()

//* 用户接口
interface User {
	id: string
	username: string
	email: string
	role: 'ADMIN' | 'USER' | null
}

//* 默认权限
const defaultRole: 'ADMIN' | 'USER' = 'USER'

//* 用户列表
const users = ref<User[]>([])

//* 数据是否加载中
const loading = ref(true)

//* 关键词查找
const search = ref('')
const filterUsers = computed(() => {
	return users.value.filter(data =>
		!search.value
		|| data.username.toLowerCase().includes(search.value.toLowerCase())
		|| data.email.toLowerCase().includes(search.value.toLowerCase())
		|| (data.role && data.role.toString().toLowerCase().includes(search.value.toLowerCase()))
	)
})

//* 当前编辑的用户信息
const ruleForm = reactive<{
	id: string
	username: string
	email: string
	role: 'ADMIN' | 'USER' | null
}>({
	id: null,
	username: '',
	email: '',
	role: null
})

//? 表单ref 不能绑定 需要直接 ref = 'ruleFormRef'
const ruleFormRef = ref<FormInstance>()

//* 验证规则
const rules = reactive<FormRules<typeof ruleForm>>({
	username: [
		{ required: true, message: '请输入用户名', trigger: 'blur' }
	],
	email: [
		{ required: true, message: '请输入邮箱', trigger: 'blur' },
		{ type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] }
	]
})

//* 可以选择的行
const selectable = (row: User) => row.role !== 'ADMIN'

//* 是否显示编辑对话框
const dialogFormVisible = ref(false)

//* 编辑用户信息
const EditRow = (selectedUser: User) => {
	dialogFormVisible.value = true

	//* 没有必要去查询 数据存储在 users 中
	// simpleRequest(Api.getUserById, selectedUser.id, data => {
	//   Object.assign(ruleForm, data.data)
	// })
	Object.assign(ruleForm, selectedUser)
	op.value = 'update'
}

//? 清空编辑框信息
const resetForm = () => {
	Object.assign(ruleForm, {
		id: null,
		username: '',
		email: '',
		role: null
	})
}

//* 关闭弹框
const closeEditDialog = () => {
	resetForm()
	dialogFormVisible.value = false
}

const op = ref<'add' | 'update'>('')

//* 添加用户
const openAddDialog = () => {
	resetForm()
	dialogFormVisible.value = true
	op.value = 'add'
}

//* 是否正在提交
const isSubmitting = ref(false)

//? 提交更新 必须按照 ElementPlus 的规范来写 不然会出现bug: 哭()
const submitEdit = (form) => {
	if (isSubmitting.value) return

	form?.validate((valid) => {
		if (!valid) {
			showMessage(op === 'add' ? '添加用户失败' : '更新用户信息失败', 'error')
			return
		}
		isSubmitting.value = true

		const formDataCopy = { ...ruleForm }


		op.value === 'add'
			? simpleRequest(Api.createUser, formDataCopy, _ => {
				users.value.push(formDataCopy)
			}, null, '添加用户失败')
			: simpleRequest(Api.updateUserById, ruleForm, _ => {
				const currentIndex = users.value.findIndex(user => user.id === formDataCopy.id)
				if (~currentIndex) users.value[currentIndex] = { ...formDataCopy }
				//! 实时响应 当修改的信息是我的时候
				if (formDataCopy.id === userStore.user.id) userStore.setUser(formDataCopy)
			}, null, '更新用户信息失败')

		isSubmitting.value = false

		closeEditDialog()
	})

}


//* 删除用户信息
const deleteRow = (selectedUser: User) => {
	simpleRequest(Api.deleteUserById, selectedUser.id, _ => {
		users.value = users.value.filter(user => user.id !== selectedUser.id)
	})
}

//* 挂载时获取用户列表
onMounted(() => {
	loading.value = true

	simpleRequest(Api.getAllUsers, null, (data) => {
		users.value = data.data.map((userData: any) => ({
			id: userData.id,
			username: userData.username,
			email: userData.email,
			role: userData.role ?? defaultRole
		}))
	})

	loading.value = false
})
</script>

<style scoped>
.controls {
	position: fixed;
	top: 3vh;
	right: 5vw;
}
</style>